home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / BuildingBlocks / WriteLineWindow.cp < prev    next >
Encoding:
Text File  |  1995-07-28  |  22.9 KB  |  1,118 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        WriteLineWindow.cp
  3.  
  4.     Copyright:    © 1991-1994 by Apple Computer, Inc.
  5.                 All rights reserved.
  6.  
  7.     Part of the AOCE Sample SMSAM Package.  Consult the license
  8.     which came with this software for your specific legal rights.
  9.  
  10. */
  11.  
  12.  
  13.  
  14. #ifndef __TYPES__
  15. #include <Types.h>
  16. #endif
  17.  
  18. #ifndef __MENUS__
  19. #include <Menus.h>
  20. #endif
  21.  
  22. #ifndef __WINDOWS__
  23. #include <Windows.h>
  24. #endif
  25.  
  26. #ifndef __WRITELINEWINDOW__
  27. #include "WriteLineWindow.h"
  28. #endif
  29.  
  30. #ifndef __MEMORY__
  31. #include <Memory.h>
  32. #endif
  33.  
  34. #ifndef __LIMITS__
  35. #include <Limits.h>
  36. #endif
  37.  
  38. #ifndef __ERRORS__
  39. #include <Errors.h>
  40. #endif
  41.  
  42. #ifndef __EVENTS__
  43. #include <Events.h>
  44. #endif
  45.  
  46. #ifndef __OSEVENTS__
  47. #include <OSEvents.h>
  48. #endif
  49.  
  50. #ifndef __STDIO__
  51. #include <stdio.h>
  52. #endif
  53.  
  54. /***********************************|****************************************/
  55.  
  56.  
  57. const short kWWHMargin = 5;
  58. const short kWWVMargin = 10;
  59. const short kForceDepth = 16;
  60.  
  61. enum { forceUnchanged, forceOn, forceOff };
  62.  
  63. const short    CODEV = 1;         //console device number
  64.  
  65.     typedef struct ForceState {
  66.         Boolean        toWindow;
  67.         Boolean        toFile;
  68.     } ForceState;
  69.  
  70. /***********************************|****************************************/
  71.  
  72.     WindowPtr    gDebugWindowPtr = nil;    
  73.     short        gLines;
  74.     short        gPerLine;                    //    number of characters per line
  75.     long        gTotal;                        //    number of characters in all lines together
  76.     char**        gText = nil;                //    the ring buffer: blanks pad each line to 80 chars
  77.     long**        gLineLens;                    /*    # of real characters in each line; (*gLinesLens)^[0]
  78.                                                 is # of characters in the line that begins with
  79.                                                         (*gText)^[0] */
  80.  
  81.     long        gFirst;                        //    where in the ring buffer the top line starts
  82.     long        gLast;                        //    where in the ring buffer the bottom line starts
  83.     short        gPos;                        //    number of characters so far in the bottom line
  84.  
  85.     short        gHeight;                    //    font height
  86.     short        gLnAscent;                    //    font ascent
  87.     short        gWidMax;                    //    font char width (must be monospaced)
  88.     ControlHandle    gSBars[2];                //    the window scroll bars
  89.     Point        gScrollOffset;                //    the position to which we are scrolled
  90.     Point        gViewSize;                    //    total view size
  91.     Point        gEndOfText;                    //    the pen position after drawing all the lines
  92.  
  93.     Rect        gStdDrag;
  94.     Rect        gStdSize;
  95.     VHSelect    gOrthogonal[2];
  96.     WindowRecord        gWRec;
  97.     RgnHandle        gARgn;
  98.  
  99.     Boolean        gGotRefNum;
  100.     short        gRefNum;                    //    refNum for redirect output
  101.     short        gVRefNum;                    //    likewise, vrefNum
  102.  
  103.     ForceState    gForceStack[kForceDepth];
  104.     short        gForcePtr;
  105.  
  106.     char* gHexStr = "0123456789abcdef";
  107.     
  108.     Boolean        gScrollWindowWhenTextIsAdded = true;
  109.     Boolean        gWrToWindow = false;
  110.     Boolean        gWrToFile = false;
  111.  
  112.     Boolean        gWWDirty = false;            //    whether unflushed data has been written.
  113.  
  114. /***********************************|****************************************/
  115.  
  116. void WWInstall(void);
  117. long WWBaseLine(short ln);
  118. void WWDoScrolling(void);
  119. void WWFlushOutputFile(void);
  120. void WWNewLine(void);
  121. void WWTrackScroll(ControlHandle aControl, short partCode);
  122. void WWShowPoint(Point pt);
  123.  
  124. /***********************************|****************************************/
  125.  
  126. #pragma segment WWSeg
  127. RgnHandle GetSaveVisRgn(void)
  128. {
  129.     const long addr    = 0x09F2;
  130.     
  131.     return * (RgnHandle *) addr;
  132. }
  133.  
  134. #pragma segment WWSeg
  135. VHSelect LongerSide(Rect& r)
  136. {
  137.         if ((r.bottom - r.top) >= (r.left - r.right))
  138.             return v;
  139.         else
  140.             return h;
  141. }
  142.  
  143.  
  144. #pragma segment WWSeg
  145. void WindowFocus(void)
  146. {
  147.     SetPort(gDebugWindowPtr);
  148.     SetOrigin(0, 0);
  149.     ClipRect(&qd.thePort->portRect);
  150. }
  151.  
  152.  
  153. #pragma segment WWSeg
  154. void ContentFocus(void)
  155. {    Rect        r;
  156.  
  157.     SetPort(gDebugWindowPtr);
  158.     SetOrigin(gScrollOffset.h, gScrollOffset.v);
  159.     * ( Rect *) &r = * ( Rect *) & qd.thePort->portRect;
  160.     r.right = r.right - 15;
  161.     r.bottom = r.bottom - 15;
  162.     ClipRect(&r);
  163. }
  164.  
  165.  
  166. #pragma segment WWInit
  167. void WWInit(short numLines, short numCharsPerLine)
  168. {    
  169.     gDebugWindowPtr = NULL;
  170.  
  171.     gGotRefNum = false;
  172.     gWrToWindow = true;
  173.     gWrToFile = true;
  174.  
  175.     WWInstall();
  176.  
  177.     gForcePtr = 0;
  178.  
  179.     gLines = numLines;
  180.     gPerLine = numCharsPerLine;
  181.     gTotal = gLines * gPerLine;
  182.  
  183.     gText = (char **) NewHandleClear(gTotal);
  184.     if (gText == NULL)
  185.     {
  186.         DebugStr ("\pNot enough memory to allocate the Debug Window''s Line Array: " );
  187.         return ;
  188.     }
  189.  
  190.     gLineLens = (long **) NewHandleClear (gLines*sizeof(long));
  191.     if (gLineLens == NULL)
  192.     {
  193.         DisposeHandle(Handle(gText));
  194.         DebugStr ("\pNot enough memory to allocate the Debug Window''s LineLen Array: ");
  195.         return;
  196.     }
  197.  
  198.     gFirst = 0;
  199.     gLast = gTotal - gPerLine;
  200.     gPos = 0;
  201.  
  202.     gOrthogonal[v] = h;
  203.     gOrthogonal[h] = v;
  204. }
  205.  
  206.  
  207. #pragma segment WWInit
  208. void WWNew(Rect *bounds, Str255 windowTitle, Boolean goAway, Boolean visible, short outputFont, short outputSize)
  209. {    FontInfo fInfo;
  210.     GrafPtr        savePort;
  211.  
  212.     GetPort(&savePort);
  213.     if (gDebugWindowPtr == NULL)
  214.     {
  215.         gDebugWindowPtr = NewWindow(nil, bounds, windowTitle, visible, documentProc, (WindowPtr) -1, goAway, 0);
  216.  
  217.         SetRect(&gStdDrag, 4, 24, qd.screenBits.bounds.right - 4, qd.screenBits.bounds.bottom - 4);    //this is suggested in Inside Macintosh
  218.         SetRect(&gStdSize, 20, 20, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom - 20);        //arbitrary Minimum size; Maximum size is screen
  219.  
  220.         gARgn = NewRgn();
  221.  
  222.         SetPt(&gEndOfText, kWWHMargin, (short) WWBaseLine(gLines));
  223.  
  224.         SetPort(gDebugWindowPtr);
  225.         TextFont(outputFont);
  226.         TextSize(outputSize);
  227.         GetFontInfo(&fInfo);
  228.  
  229.         gHeight = fInfo.ascent + fInfo.descent + fInfo.leading;
  230.         gLnAscent = fInfo.ascent;
  231.         gWidMax = fInfo.widMax;
  232.         SetPt(&gViewSize, (2 * kWWHMargin) + (gPerLine * fInfo.widMax), (2 * kWWVMargin) + (gHeight * gLines));
  233.  
  234.         //scroll bars
  235.         for ( VHSelect vhs = v; vhs <= h; ++ vhs ) {
  236.             gSBars[vhs] = NewControl(gDebugWindowPtr, &gDebugWindowPtr->portRect, "\p", false, 0, 0, 1, scrollBarProc, 0);
  237.         }
  238.  
  239.         gScrollOffset.v = gScrollOffset.h = 0;
  240.  
  241.         //put the scroll bars in the right place
  242.         WWGrown();
  243.  
  244.         //force an update
  245.         WWUpdateEvent();
  246.  
  247.         //scroll to the end, in case there is some information that needs to be displayed
  248.         SetCtlValue(gSBars[v], LONG_MAX);
  249.         WWDoScrolling();
  250.     }
  251.     SetPort(savePort);
  252. }
  253.  
  254. #pragma segment WWInit
  255. void WWNewDefault(void)
  256. {    Rect    aRect;
  257.     Str255        title ;
  258.  
  259.     SetRect (&aRect, 16, 40, 16+6*80+16, 40+12*36);
  260.     PLstrcpy ( title, LMGetCurApName() );
  261.     PLstrcat ( title, "\p Debug Window");
  262.     
  263.     WWNew (&aRect, title, true, true, 1, 9);
  264. }
  265.  
  266.  
  267.  
  268. #pragma segment WWSeg
  269. void WWActivateEvent(short modifiers)
  270. {    Rect r;
  271.         GrafPtr        savePort;
  272.  
  273.     GetPort(&savePort);
  274.  
  275.     WindowFocus();
  276.  
  277.     r = qd.thePort->portRect;
  278.  
  279.     if ( modifiers & 0x01 )
  280.     {
  281.         ShowControl ( gSBars[v] );
  282.         ShowControl ( gSBars[h] );
  283.     }
  284.     else
  285.     {
  286.         HideControl ( gSBars[v] );
  287.         HideControl ( gSBars[h] );
  288.     }
  289.  
  290.     DrawGrowIcon(gDebugWindowPtr);
  291.  
  292.     SetPort(savePort);
  293. }
  294.  
  295.  
  296. #pragma segment WWSeg
  297. pascal void WWAddText(Ptr textBuf, long byteCount)
  298. {
  299.     char const BS = 8;
  300.     Boolean gotEOL;
  301.     QDByte        b;
  302.     Ptr        startPtr;
  303.     long        startCount;
  304.     PenState        ps;
  305.     GrafPtr        savePort;
  306.     Boolean        deleted;
  307.     Rect        r;
  308.  
  309.     long        count;
  310.     long        filePos ;
  311.  
  312.     gWWDirty = gWWDirty && ( byteCount > 0 );
  313.         
  314.     if (gWrToFile)
  315.         if (gGotRefNum)
  316.         {
  317.             count = byteCount;
  318.             if ( FSWrite(gRefNum, &count, textBuf) != noErr )
  319.             {
  320.             }
  321.             if ( GetFPos (gRefNum, &filePos) == noErr) 
  322.                 if ( SetEOF (gRefNum, filePos) == noErr ) 
  323.                     WWFlushOutputFile();
  324.         }
  325.  
  326.     if (gWrToWindow)
  327.     {
  328.         if (gDebugWindowPtr != NULL)
  329.             GetPort(&savePort);
  330.  
  331.         deleted = false;
  332.  
  333.         while ( byteCount > 0){
  334.             gotEOL = false;
  335.             startPtr = textBuf;
  336.             startCount = byteCount;
  337.  
  338.             while ( (byteCount > 0) && (gPos < gPerLine) && (!gotEOL)){
  339.                 b = (*QDPtr(textBuf));
  340.                 byteCount = byteCount - 1;
  341.                 textBuf = Ptr(((long)textBuf) + 1);
  342.  
  343.                 if ((b == 13) || ( b == 10 ))
  344.                 {    b = '\n';
  345.                     gotEOL = true;
  346.                 }
  347.                 else if (b != BS)
  348.                 {
  349.                     (*gText)[gLast+gPos++] = b;
  350.                 } 
  351.                 else if (gPos > 0)  // Backspace -- don't backspace past beginning of line!
  352.                 {
  353.                     SetRect(&r, gEndOfText.h - gWidMax, gEndOfText.v - gLnAscent, gEndOfText.h, gEndOfText.v + gHeight - gLnAscent);
  354.                     gEndOfText.h = gEndOfText.h - gWidMax;
  355.  
  356.                     if (gDebugWindowPtr != NULL)
  357.                     {
  358.                         ContentFocus();
  359.                         EraseRect(&r);
  360.                     }
  361.  
  362.                     gPos--;
  363.                     deleted = true;
  364.                 }                
  365.                 else
  366.                     deleted = true;
  367.                 }
  368.  
  369.             if (!deleted && (gDebugWindowPtr != NULL))
  370.             {
  371.                 ContentFocus();
  372.                 MoveTo(gEndOfText.h, gEndOfText.v);
  373.                 DrawText(QDPtr(startPtr), 0, (short) (startCount - byteCount - gotEOL) );
  374.                 GetPenState(&ps);
  375.                 gEndOfText = ps.pnLoc;
  376.             }
  377.  
  378.             if ((gPos >= gPerLine) || gotEOL)
  379.             {
  380.                 (*gLineLens)[gLast / gPerLine] = gPos;    //remember # characters in this line
  381.  
  382.                 WWNewLine();
  383.                 if ((byteCount > 0) && (!gotEOL))
  384.                 {
  385.                     (*gText)[gLast] = '…';
  386.                     gPos = 1;
  387.                 }
  388.             }
  389.         }
  390.  
  391.         (*gLineLens)[gLast / gPerLine] = gPos;
  392.  
  393.         if (gDebugWindowPtr != NULL)
  394.             SetPort(savePort);
  395.     }
  396. }
  397.  
  398. /***********************************|****************************************/
  399.  
  400. void WWFlushOutputFile(void)
  401. {
  402.     if ( gWrToFile && gWWDirty )
  403.     {    ParamBlockRec    pb;
  404.  
  405.         pb.ioParam.ioRefNum = gRefNum;
  406.         
  407.         PBFlushFileSync(&pb);
  408.         gWWDirty = false;
  409.     }
  410. }
  411.  
  412. /***********************************|****************************************/
  413.  
  414. #pragma segment WWSeg
  415. long WWBaseLine(short ln)
  416. {
  417.     return kWWVMargin + (ln - 1) * gHeight;
  418. }
  419.  
  420.  
  421. #pragma segment WWSeg
  422. void WWDoScrolling(void)
  423. {    Point newOffset;
  424.     Point delta;
  425.         
  426.     newOffset.v = GetCtlValue(gSBars[v]);
  427.     delta.v = gScrollOffset.v - newOffset.v;
  428.     newOffset.h = GetCtlValue(gSBars[h]);
  429.     delta.h = gScrollOffset.h - newOffset.h;
  430.  
  431.     if ((delta.h != 0) || (delta.v != 0))
  432.         {
  433.         ContentFocus();
  434.  
  435.         ScrollRect(&qd.thePort->portRect, delta.h, delta.v, gARgn);
  436.         gScrollOffset = newOffset;
  437.  
  438.         InvalRgn(gARgn);
  439.  
  440.         WWUpdateEvent();
  441.         }
  442. }
  443.  
  444.  
  445. #pragma segment WWSeg
  446. void WWDraw(void)
  447. {    
  448.     short        y;
  449.     long        start;
  450.     long        line;
  451.     PenState        ps;
  452.  
  453.     y = kWWVMargin;            //initial y corodinate
  454.  
  455.     start = gFirst;            //offset to first character of next line to draw
  456.     line = start / gPerLine; //index into gLineLens array for next line to draw; always start / gPerLine
  457.  
  458.     for ( short i = 1; i <= gLines; ++i )
  459.     {
  460.         MoveTo(kWWHMargin, y);
  461.  
  462.         HLock(Handle(gText));
  463.         DrawText(QDPtr((*gText)), (short) start, (short) (*gLineLens)[line]);
  464.         HUnlock(Handle(gText));
  465.  
  466.         y += gHeight;
  467.         start = start + gPerLine;
  468.         line++;
  469.  
  470.         if (start == gTotal)
  471.         {
  472.             start = line = 0;
  473.         }
  474.     }
  475.  
  476.     GetPenState(&ps);            //remember position of last character drawn
  477.     gEndOfText = ps.pnLoc;
  478. }
  479.  
  480.  
  481. #pragma segment WWSeg
  482. void WWEndForce(void)
  483. {
  484.     if (gForcePtr > 0)
  485.     {
  486.         gWrToWindow = gForceStack[gForcePtr].toWindow;
  487.         gWrToFile = gForceStack[gForcePtr].toFile;
  488.         gForcePtr--;
  489.     }
  490. }
  491.  
  492.  
  493. #pragma segment WWSeg
  494. void WWForceOutput(short wrToWindow, short wrToFile)
  495. {
  496.     if (gForcePtr < kForceDepth)
  497.     {
  498.         gForcePtr++;
  499.  
  500.         gForceStack[gForcePtr].toWindow = gWrToWindow;
  501.         gForceStack[gForcePtr].toFile = gWrToFile;
  502.  
  503.         if (wrToWindow != forceUnchanged)
  504.             gWrToWindow = wrToWindow == forceOn;
  505.  
  506.         if (wrToFile != forceUnchanged )
  507.             gWrToFile = wrToFile == forceOn;
  508.     }
  509. }
  510.  
  511.  
  512. #pragma segment WWSeg
  513. void WWGrown(void)
  514. {    Rect        r;
  515.         ControlHandle        anSBar;
  516.         short        newMax;
  517.         GrafPtr        savePort;
  518.  
  519.     GetPort(&savePort);
  520.  
  521.     WindowFocus();
  522.     SetRect (&r, 0, 0, 0, 0 );
  523.     ClipRect(&r);
  524.  
  525.     for (VHSelect vhs = v; vhs <= h; ++vhs )
  526.     {
  527.         anSBar = gSBars[vhs];
  528.  
  529.         r = qd.thePort->portRect;
  530.  
  531.         // Calculate new position of scroll bar
  532.         (( short *) &r.top)[vhs] = (( short *) &r.top)[vhs] - 1;
  533.         (( short *) &r.top)[gOrthogonal[vhs]] = (( short *) &r.bottom)[gOrthogonal[vhs]] - 15;
  534.         (( short *) &r.bottom)[vhs] = (( short *) &r.bottom)[vhs] - 14;
  535.         (( short *) &r.bottom)[gOrthogonal[vhs]] = (( short *) &r.top)[gOrthogonal[vhs]] + 16;
  536.  
  537.         //Move the scroll bar
  538.         MoveControl(anSBar, r.left, r.top);
  539.         SizeControl(anSBar, r.right-r.left, r.bottom-r.top);
  540.  
  541.         if ( vhs == v )
  542.             newMax = gViewSize.v - (r.bottom - r.top);
  543.         else
  544.             newMax = gViewSize.h - (r.right - r.left );
  545.         
  546.         if (newMax < 0)
  547.             newMax = 0;
  548.         SetCtlMax(anSBar, newMax);
  549.     }
  550.  
  551.     WWInvalGrowBox();
  552.  
  553.     WWDoScrolling();    //in case we are showing too much white space
  554.  
  555.     SetPort(savePort);
  556. }
  557.  
  558.  
  559. #pragma segment WWSeg
  560. void WWInvalGrowBox(void)
  561. {    Rect     r;
  562.  
  563.     r = qd.thePort->portRect;
  564.     r.top = r.bottom - 15;
  565.     r.left = r.right - 15;
  566.  
  567.     InvalRect(&r);
  568. }
  569.  
  570. /***********************************|****************************************/
  571.  
  572. Boolean GetDefaultWindowInformation ( short dialogID, Boolean& visible, Rect & screenRect );
  573. Boolean SetDefaultWindowInformation ( DialogPtr dP, short dialogID );
  574.  
  575. /***********************************|****************************************/
  576.  
  577. #pragma segment WWSeg
  578. void WWMouseDown(short where, Point pt, short modifiers)
  579. {    GrafPtr        savePort;
  580.     
  581.     GetPort(&savePort);
  582.  
  583.     switch (where) {
  584.         case inDrag:
  585.             DragWindow(gDebugWindowPtr, pt, &gStdDrag);
  586.             break;
  587.             
  588.         case inGrow:
  589.             WindowFocus();
  590.  
  591.             long growResult = GrowWindow(gDebugWindowPtr, pt, &gStdSize);
  592.             if (growResult != 0)
  593.             {    short newH = (short) (growResult & 0xffff );
  594.                 short newV = (short) (growResult >> 16);
  595.                 
  596.                 WWInvalGrowBox();
  597.                 SizeWindow(gDebugWindowPtr, newH, newV, true);
  598.                 SetDefaultWindowInformation ( gDebugWindowPtr, -1 );
  599.  
  600.                 WWGrown();
  601.             }
  602.             break;
  603.             
  604.         case inGoAway:
  605.             if (TrackGoAway(gDebugWindowPtr, pt)) {
  606.                 SetDefaultWindowInformation ( gDebugWindowPtr, -1 );
  607.                 HideWindow(gDebugWindowPtr);
  608.             }
  609.             break;
  610.             
  611.         case inContent:
  612.             if (gDebugWindowPtr == FrontWindow())
  613.             {
  614.                 WindowFocus();
  615.                 GlobalToLocal(&pt);
  616.                 
  617.                 ControlHandle whichControl;
  618.                 long partCode = FindControl(pt, gDebugWindowPtr, &whichControl);
  619.                 switch (partCode) 
  620.                 {
  621.                     case inUpButton:
  622.                     case inDownButton:
  623.                     case inPageUp:
  624.                     case inPageDown:
  625.                         partCode = TrackControl(whichControl, pt, NewControlActionProc((ProcPtr) &WWTrackScroll));
  626.                         break;
  627.                         
  628.                     case inThumb:
  629.                         partCode = TrackControl(whichControl, pt, NULL);
  630.                         WWDoScrolling();
  631.                         break;
  632.                     
  633.                     case 0:
  634.                         break;
  635.                 }
  636.             }
  637.             else
  638.                 SelectWindow(gDebugWindowPtr);
  639.                 
  640.             break;            
  641.     }
  642.  
  643.     SetPort(savePort);
  644. }
  645.  
  646.  
  647. #pragma segment WWSeg
  648. void WWNewLine(void)
  649. {    GrafPtr         savePort;
  650.         Point        pt;
  651.         Rect        r;
  652.  
  653.     GetPort(&savePort);
  654.  
  655.     SetPt(&pt, kWWHMargin, gEndOfText.v);
  656.  
  657.     if ( gScrollWindowWhenTextIsAdded )
  658.         WWShowPoint(pt);
  659.  
  660.     gLast = gFirst;
  661.     gPos = 0;
  662.     (*gLineLens)[gLast / gPerLine] = gPos;    //remember # characters in new line
  663.  
  664.     gFirst = gFirst + gPerLine;
  665.     if (gFirst == gTotal)
  666.         gFirst = 0;
  667.  
  668.     SetPt(&gEndOfText, kWWHMargin, (short) WWBaseLine(gLines));
  669.  
  670.     if ( gDebugWindowPtr )
  671.     {
  672.         ContentFocus();
  673.         
  674.         SetRect(&r, kWWHMargin, kWWVMargin - gLnAscent, gViewSize.h, gEndOfText.v + gHeight - gLnAscent);
  675.         ScrollRect(&r, 0, -gHeight, gARgn);
  676.         InvalRgn(gARgn);
  677.  
  678.         WWUpdateEvent();
  679.     }
  680.  
  681.     SetPort(savePort);
  682. }
  683.  
  684.  
  685. OSErr WWRedirect(short vRefNum, long dirID, Str255 fileNameBase)
  686. {    OSErr         err;
  687.     Boolean        append;
  688.     long        x;
  689.  
  690.     if (gGotRefNum)
  691.     {
  692.         // Truncate the file to current position
  693.         err = GetFPos(gRefNum, &x);
  694.         err = SetEOF(gRefNum, x);
  695.  
  696.         if (FSClose(gRefNum) != noErr) /*??? error closing file ???*/;
  697.             if (FlushVol(NULL, gVRefNum) != noErr) /*??? Another fine mess ???*/;
  698.                 gGotRefNum = false;
  699.     }
  700.     
  701.     Str255 fileName;
  702.     PLstrcpy ( fileName, fileNameBase );
  703.     
  704.     append = false;
  705.  
  706.     if (PLstrlen(fileName) > 0 )
  707.     {
  708.         err = HCreate(vRefNum, dirID, fileName, 'R*ch', 'TEXT');
  709.  
  710.         if ((err == noErr) || (err == dupFNErr))
  711.         {
  712.             err = HOpen(vRefNum, dirID, fileName, fsRdWrPerm, &gRefNum);
  713.             gVRefNum = vRefNum;
  714.  
  715.             gGotRefNum = err == noErr;
  716.  
  717.             if (gGotRefNum)
  718.                 if (append)
  719.                 {
  720.                     err = GetEOF(gRefNum, &x);
  721.                     err = SetFPos(gRefNum, fsFromStart, x);
  722.                 }
  723.                 else
  724.                     err = SetEOF (gRefNum, 0);
  725.             else
  726.                 err = noErr;
  727.         }
  728.     }
  729.     return noErr;
  730. }
  731.  
  732. void WWScroll(short howManyLines)
  733. {    short     val;
  734.         GrafPtr        savePort;
  735.  
  736.     GetPort(&savePort);
  737.     val = GetCtlValue(gSBars[v]);
  738.     if (((howManyLines < 0) && (val > GetCtlMin(gSBars[v]))) ||
  739.        ((howManyLines > 0) && (val < GetCtlMax(gSBars[v]))))
  740.         {
  741.         SetCtlValue(gSBars[v], val + howManyLines * gHeight);
  742.         WWDoScrolling();
  743.         }
  744.     SetPort(savePort);
  745. }
  746.  
  747.  
  748. void WWShowPoint(Point pt)
  749. {    Point     minToSee;
  750.         short        deltaCd;
  751.  
  752.     if (gDebugWindowPtr != NULL)
  753.         {
  754.         WindowFocus();
  755.  
  756.         SetPt(&minToSee, 50, gHeight);
  757.  
  758.         // the following code is actually better than writing a loop with VHSelect
  759.         deltaCd = pt.v + minToSee.v - (qd.thePort->portRect.bottom - 15 + gScrollOffset.v);
  760.         if (deltaCd <= 0)
  761.         {
  762.             deltaCd = pt.v - minToSee.v - (qd.thePort->portRect.top + gScrollOffset.v);
  763.             if (deltaCd >= 0)
  764.                 deltaCd = 0;
  765.         }
  766.         SetCtlValue(gSBars[v], GetCtlValue(gSBars[v]) + deltaCd);
  767.  
  768.         deltaCd = pt.h + minToSee.h - (qd.thePort->portRect.right - 15 + gScrollOffset.h);
  769.         if (deltaCd <= 0)
  770.         {
  771.             deltaCd = pt.h - minToSee.h - (qd.thePort->portRect.left + gScrollOffset.h);
  772.             if (deltaCd >= 0)
  773.                 deltaCd = 0;
  774.         }
  775.         SetCtlValue(gSBars[h], GetCtlValue(gSBars[h]) + deltaCd);
  776.  
  777.         WWDoScrolling();
  778.         }
  779. }
  780.  
  781.  
  782. #pragma segment WWSeg
  783. void WWTrackScroll(ControlHandle aControl, short partCode)
  784. {    Boolean         up;
  785.         short        ctlValue;
  786.         VHSelect        vhs;
  787.         Rect        r;
  788.         short        delta;
  789.  
  790.     if (partCode != 0)
  791.         {
  792.         up = (partCode == inUpButton) || (partCode == inPageUp);
  793.         ctlValue = GetCtlValue(aControl);
  794.  
  795.       //avoid flicker in setting thumb, if (user tries to scroll past end
  796.         if ((up && (ctlValue > GetCtlMin(aControl))) ||
  797.            (!up && (ctlValue < GetCtlMax(aControl))))
  798.             {
  799.             r = (*aControl)->contrlRect;   //heap may compact when we call LongerSide
  800.             vhs = LongerSide(r);          //this tells us which way we are scrolling
  801.             
  802.             if ((partCode == inPageUp) || (partCode == inPageDown))
  803.                 if ( vhs == v )
  804.                     delta = gDebugWindowPtr->portRect.bottom - gDebugWindowPtr->portRect.top;
  805.                 else
  806.                     delta = gDebugWindowPtr->portRect.right - gDebugWindowPtr->portRect.left;
  807.             else
  808.                 delta = gHeight;
  809.  
  810.             if (up)
  811.                 delta = - delta;
  812.  
  813.             SetCtlValue(aControl, ctlValue + delta);
  814.             WWDoScrolling();
  815.  
  816.             WindowFocus();
  817.             }
  818.         }
  819. }
  820.  
  821.  
  822. #pragma segment WWSeg
  823. void WWUpdateEvent(void)
  824. {    GrafPtr         savePort;
  825.         RgnHandle        saveSaveVisRgn;
  826.         RgnHandle        saveVisRgn;
  827.  
  828.     if ((gDebugWindowPtr != NULL) &&
  829.         (!EmptyRgn( ((WindowPeek)gDebugWindowPtr)->port.visRgn))) 
  830.     {
  831.         GetPort(&savePort);
  832.  
  833.         saveSaveVisRgn = NewRgn();
  834.         saveVisRgn = GetSaveVisRgn();
  835.  
  836.         CopyRgn(saveVisRgn, saveSaveVisRgn);
  837.  
  838.         BeginUpdate(gDebugWindowPtr);
  839.  
  840.         WindowFocus();
  841.  
  842.         EraseRect(&qd.thePort->portRect);
  843.  
  844.         DrawGrowIcon(gDebugWindowPtr);
  845.         DrawControls(gDebugWindowPtr);
  846.  
  847.         ContentFocus();
  848.         WWDraw();
  849.  
  850.         EndUpdate(gDebugWindowPtr);
  851.  
  852.         CopyRgn(saveSaveVisRgn, saveVisRgn);
  853.         DisposeRgn(saveSaveVisRgn);
  854.  
  855.         SetPort(savePort);
  856.     }
  857. }
  858.  
  859.  
  860. #pragma segment WWSeg
  861. char WWReadCh(void)
  862. {    GrafPtr         savePort;
  863.         char        ch;
  864.         EventRecord        anEvent;
  865.         Rect        r;
  866.  
  867.     GetPort(&savePort);
  868.  
  869.     ContentFocus();
  870.  
  871.     SetRect(&r, gEndOfText.h, gEndOfText.v - gLnAscent, gEndOfText.h + gWidMax, gEndOfText.v + gHeight - gLnAscent);
  872.  
  873.     FillRect(&r, ( Pattern*) &qd.black);
  874.     while ( GetOSEvent(keyDownMask+autoKeyMask, &anEvent))
  875.         ;
  876.     EraseRect(&r);
  877.  
  878.     ch = char(((anEvent.message) & charCodeMask));
  879.  
  880.     SetPort(savePort);
  881.  
  882.     return ch;
  883. }
  884.  
  885.  
  886. #pragma segment WWSeg
  887. pascal long WWREADLN(Ptr buffer, short byteCount)
  888. {    
  889.     const char CR = 13;
  890.     const char BS = 8;
  891.  
  892.     short len = 0;
  893.     char ch;
  894.     do {
  895.         ch = WWReadCh();
  896.         if (ch != BS )
  897.         {
  898.             WWAddText(&ch, 1);
  899.             buffer[len++] = ch;
  900.         }
  901.         else if (len > 0)
  902.         {
  903.             WWAddText(&ch, 1);
  904.             buffer[--len] = ' ';
  905.         }
  906.     } while ( ! ( (ch==CR) || (len == byteCount)) );
  907.  
  908.    return len;
  909. }
  910.  
  911.  
  912. void IDUWritelnWindow(void) //Writeln UWritelnWindow's compile time.
  913. {
  914. //    Writeln('UWritelnWindow of ', COMPDATE, ' & ', COMPTIME);
  915. }
  916.  
  917.  
  918. long    wwFAccess(Ptr fName, long opCode, long arg );
  919. long    wwClose(long refNum);
  920. long    wwRead(long fdesc, long bufp, long count );
  921. long    wwWrite(long fdesc, long bufP, long count);
  922. long    wwIoctl(long fdesc, long request, long arg );
  923.  
  924. long    _addDevHandler( long slot, Ptr dvName, ProcPtr dvFAccess, ProcPtr dvClose, ProcPtr dvRead, ProcPtr dvWrite, ProcPtr dvIoctl );
  925.         
  926. void WWInstall(void)
  927. {    
  928.     #ifndef THINK_CPLUS
  929.     long  slot = _addDevHandler(CODEV, 0,
  930.                     (ProcPtr) wwFAccess, (ProcPtr) wwClose, (ProcPtr) wwRead, (ProcPtr) wwWrite, (ProcPtr) wwIoctl );
  931.     
  932.     setvbuf ( stdout, nil, 64, 100 );
  933.     #endif
  934. }
  935.  
  936.  
  937. /*
  938. --    Paul's Writeln routines  ----------------------------------------------------------------
  939. */
  940. Boolean WWEvent(EventRecord* event )
  941. {
  942.     WindowPtr        WindowPointedTo;        //window where the mouse is
  943.     Point        MouseLoc;
  944.     short        WindoPart;        //component of window where mouse is
  945.     Boolean        result = false;
  946.     
  947.     switch ( event->what )
  948.     {
  949.         case mouseDown:
  950.             {
  951.                 MouseLoc = event->where;
  952.                 WindoPart = FindWindow(MouseLoc, &WindowPointedTo);
  953.  
  954.                 if ( (WindowPointedTo == gDebugWindowPtr))
  955.                     {
  956.                         if (WindowPointedTo != FrontWindow())
  957.                             SelectWindow(WindowPointedTo);
  958.                         else
  959.                             WWMouseDown(WindoPart, MouseLoc, event->modifiers);
  960.                         result = true;
  961.                     }
  962.             }
  963.             break;
  964.             
  965.         case activateEvt:
  966.             if (WindowPtr(event->message) == gDebugWindowPtr)
  967.                 {
  968.                     WWActivateEvent(event->modifiers);
  969.                     result = true;
  970.                 }
  971.             break;
  972.             
  973.         case updateEvt:
  974.             if (WindowPtr(event->message) == gDebugWindowPtr)
  975.                 {
  976.                     WWUpdateEvent();
  977.                     result = true;
  978.                 }
  979.             break;
  980.     }
  981.     
  982.     return result;
  983.     
  984. } //WWEvent
  985.  
  986. /*
  987. --    end Writeln routines  ------------------------------------------------------------
  988. */
  989.  
  990. /*
  991. -- Keith's WriteLineWindow routines --------------------------------------------------
  992. */
  993. #if 0
  994.  
  995. void WWAddDate(void)
  996. VAR
  997.     long        dateTime ;
  998.     Str255        tempStr255 ;
  999. {
  1000.     GetDateTime (dateTime);
  1001.     IUDateString(dateTime, shortDate, tempStr255);
  1002.     write (tempStr255, ' ');
  1003. }
  1004.  
  1005. void WWAddTime(void)
  1006. VAR
  1007.     long        dateTime ;
  1008.     Str255        tempStr255 ;
  1009. {
  1010.     GetDateTime (dateTime);
  1011.     IUTimeString(dateTime, true, tempStr255);
  1012.     write (tempStr255, ' ');
  1013. }
  1014.  
  1015. void WWAddDateTime(void)
  1016. {
  1017.     WWAddDate();
  1018.     WWAddTime();
  1019. }
  1020. #endif
  1021.  
  1022. void WWAddEncodedText (Ptr dataPtr, long size)
  1023. {
  1024.     for ( short index = 0; index < size; ++index )
  1025.     {
  1026.         char c = dataPtr[index];
  1027.         switch ( c )
  1028.         {
  1029.             case  0: case 128: c = 'ø'; break;
  1030.             case  8: case 136: c = 'Δ'; break;
  1031.             
  1032.             case 10: case 138: c = '◊'; break;
  1033.             case 13: case 141: c = '¬'; break;
  1034.             case 222: c = '∞'; break;
  1035.         }
  1036.         WWAddText ( &c, 1 );
  1037.     }
  1038. }
  1039.  
  1040. inline long IntegerMax (long a, long b )
  1041. {
  1042.     return ( a > b ) ? a : b;
  1043. }
  1044.  
  1045. Str255& NumToHexStringF(long theNumber)
  1046. {    static Str255        returnStr;
  1047.  
  1048.     returnStr[0] = sprintf ((char*) &returnStr[1], "%8x", theNumber );
  1049.     
  1050.     return returnStr;
  1051. }
  1052.  
  1053. /***********************************|****************************************/
  1054.  
  1055. void WWAddHexData (Ptr dataPtr, short dataSize )
  1056. {
  1057.     long        index ;
  1058.     Str255        result ;
  1059.     short        len ;
  1060.     char        byte ;
  1061.  
  1062.     if ( !dataPtr )
  1063.     {        
  1064.         DebugStr ("\pNo data dump, NULL data ptr");
  1065.         return;
  1066.     }
  1067.  
  1068.     if ( dataSize <= 0 )
  1069.     {
  1070.         DebugStr ("\pNo data dump, datesize <= 0");
  1071.         return;
  1072.     }
  1073.     
  1074.     long offset = 0;
  1075.  
  1076.     while (offset < dataSize)
  1077.     {
  1078.         #if 0
  1079.         WWAddText (
  1080.         write ( NumToHexStringF (offset), ':');
  1081.  
  1082.         // Put it into a Str255 because it's faster to add one string to the window than it is to add 16 
  1083.         result = '';
  1084.         for index = 0 to 15
  1085.         do
  1086.             if offset + index < dataSize
  1087.             then
  1088.                 begin
  1089.                 len = length(result);
  1090.                 byte = BytePtr(((long)dataPtr)+offset+index)^;
  1091.                 result[len+1] = gHexStr[ ((byte) >> 4)];
  1092.                 result[len+2] = gHexStr[ ((byte) & 0xF)];
  1093.                 result[len+3] = ' ';
  1094.                 //$PUSH*/ /*$R-*/ result[0] = ((char)(len + 3)); /*$POP
  1095.                 end
  1096.             else
  1097.                 begin
  1098.                 result[len+1] = ' ';
  1099.                 result[len+2] = ' ';
  1100.                 result[len+3] = ' ';
  1101.                 //$PUSH*/ /*$R-*/ result[0] = ((char)(len + 3)); /*$POP
  1102.                 end();
  1103.         write (result, '| ');
  1104.  
  1105.         WWAddEncodedText ( Ptr(((long)dataPtr)+offset), IntegerMax(dataSize - offset, 16));
  1106.  
  1107.         offset = offset + 16;
  1108.         #endif
  1109.     }
  1110. }
  1111.  
  1112. void WWShowWindow(void)
  1113. {
  1114.     SetDefaultWindowInformation ( gDebugWindowPtr, -1 );
  1115.  
  1116.     ShowWindow (gDebugWindowPtr);
  1117. }
  1118.